<script lang="ts" setup>
import { useStoreDict } from '@/store/modules/dict'
import { Delete, EditPen } from '@element-plus/icons-vue'
import { useCalcRuleDel, useGetOrderPage, useGetRulePage, useRuleAdd, useRuleDel } from '@fl/api/man-api/pricing-tool'
import { cloneDeep } from 'lodash-es'
import { nextTick, ref, toRefs } from 'vue'

import AddDialog from './dialog.vue'

const props = withDefaults(defineProps<{
    id?: string
    limit?: number
}>(), {
    limit: 20,
})

const { id, limit } = toRefs(props)
const { dicts } = useStoreDict()
const show = ref(false)
const isAdd = ref(false)
const tableRef = ref()
const tableData = ref<any>([])
const rowData = ref({})
const rowIdx = ref(Number.NaN)
const formulaIdx = ref(0) // 当前编辑公式index

// 查询已有计算规则
const params = computed(() => ({ categoryId: id.value ?? '' }))
const { data, isLoading, refetch } = useGetRulePage(params)

// 查询报价清单列表 统一单位
const { data: orderData } = useGetOrderPage(params)
const getUnit = computed(() => {
    return orderData.value?.length ? orderData.value[0].unit : ''
})

const cache = ref<any>([])

watchEffect(() => {
    if (data.value) {
        tableData.value = cloneDeep(data.value)
        cache.value = cloneDeep(data.value)
    }
})

// 添加公式
function addFormula({ $index, row }) {
    isAdd.value = true
    rowIdx.value = $index
    rowData.value = cloneDeep(row)
    show.value = true
}

// 编辑公式
function editFormula({ $index, row }, idx?: any) {
    formulaIdx.value = idx
    isAdd.value = false
    rowIdx.value = $index
    rowData.value = cloneDeep(row)
    show.value = true
}

// 规则新增公式
function setFormula(params: any) {
    tableData.value[rowIdx.value] = params
}

// 删除公式
const { mutate: mutateDel } = useRuleDel()
function colDel({ $index }, idx) {
    ElMessageBox.confirm('该操作将永久删除，是否继续?', '提示', { type: 'warning' })
        .then(() => {
            const target = tableData.value[$index].formulaList[idx]
            if (target?.formulaId) {
                mutateDel(target.formulaId, {
                    onSuccess: (res: any) => {
                        if (res.code === 200) {
                            ElMessage({ message: '操作成功', type: 'success' })
                            tableData.value[$index].formulaList.splice(idx, 1)
                        }
                        else {
                            ElMessage.error(res.msg)
                        }
                    },
                })
            }
            else {
                ElMessage({ message: '操作成功', type: 'success' })
                tableData.value[$index].formulaList.splice(idx, 1)
            }
        })
}

function colChange(val, { $index }) {
    // 添加计算方式label
    const name = dicts.jc_zjgj_calc_type.find((v: any) => v.value === String(val))?.label ?? ''
    tableData.value[$index].calcTypeName = name
}

// 删除规则
const { mutate: mutateRuleDel } = useCalcRuleDel()
function doDel({ $index, row }) {
    ElMessageBox.confirm('该操作将永久删除，是否继续?', '提示', { type: 'warning' })
        .then(() => {
            if (row?.ruleId) {
                mutateRuleDel(row.ruleId, {
                    onSuccess: () => {
                        ElMessage({ message: '操作成功', type: 'success' })
                    },
                })
            }
            else {
                ElMessage({ message: '操作成功', type: 'success' })
            }

            tableData.value.splice($index, 1)
        })
}

// 添加规则
function doAdd() {
    if (!getUnit.value) {
        ElMessage.error(`请先添加报价清单`)
        return
    }

    const len = tableData.value.length
    if (len >= limit.value) {
        ElMessage.error(`最多添加${limit.value}条数据！`)
        return
    }

    let isNext = true
    const target = tableData.value[len - 1]
    // 校验上条数据 是否填写完整
    if (len) {
        const arr = ['model', 'calcType']
        isNext = !(arr.some((key: any) => !target[key]))
    }

    if (!isNext) {
        ElMessage.error(`请填写完整第${len}条数据`)
        return
    }

    const models = tableData.value.map((v: any) => v.model)
    const arr = models.slice(0, models.length - 1)

    if (len > 1 && arr.includes(target.model)) {
        ElMessage.error(`第${len}条型号已存在`)
        return
    }

    tableData.value.push({
        calcType: '', // 计算方式
        calcTypeName: '', // 计算方式名称
        categoryId: id.value, // 组价目录id
        // ruleId: '', // 计算规则id
        formulaList: [],
        model: '', // 型号
        unit: getUnit.value,
    })

    if (tableData.value.length > 5) {
        nextTick(() => {
            tableRef.value.setScrollTop(len * 300)
        })
    }
}

const { mutate } = useRuleAdd()
function doSave(fn?: any) {
    if (!getUnit.value) {
        ElMessage.error(`请先添加报价清单`)
        return
    }

    const target = cloneDeep(tableData.value)
    if (!target.length) {
        ElMessage({ message: '请添加规则', type: 'error' })
        return
    }

    // 重复校验
    const noRepeat = new Set([...target.map((v: any) => v.model)])
    if (target.length !== noRepeat.size) {
        ElMessage.error(`存在重复型号`)
        return
    }

    const isEnpty = target.some((v: any) => !v.model)
    if (isEnpty) {
        ElMessage.error(`请填写完整再保存`)
        return
    }

    // 对于固定值 清空计算公式
    target.forEach((v: any) => {
        // 统一单位
        v.unit = getUnit.value

        if (v.calcType === 1 && v?.formulaList && v.formulaList.length) {
            v.formulaList = []
        }

        // 重置step
        if (v.formulaList) {
            v.formulaList.forEach((item: any, index: number) => {
                item.step = index + 1
            })
        }
    })

    mutate(target, {
        onSuccess: () => {
            ElMessage({ message: '操作成功', type: 'success' })
            refetch()
            if (fn)
                fn()
        },
    })
}

// 检测是否存在未保存数据
function hasDraft() {
    return cache.value.length !== tableData.value.length || JSON.stringify(cache.value) !== JSON.stringify(tableData.value)
}

defineExpose({
    doSave,
    hasDraft,
})
</script>

<template>
    <div class="mb-20 c-#1d2129 font-600">
        计算规则列表
        <!-- <span class="c-#e6a23c text-12 ml-20"><span class="px-7 py-1 rounded-10 c-#fff bg-yellow">!</span>
            请点击底部保存按钮，提交数据</span> -->
    </div>

    <el-table ref="tableRef"
              v-loading="isLoading"
              :data="tableData"
              stripe
              style="width: 100%"
              height="300"
    >
        <el-table-column label="序号"
                         type="index"
                         width="55"
        />

        <el-table-column label="型号"
                         width="280"
        >
            <template #header>
                <span><span class="mr-5 c-red">*</span>型号</span>
            </template>

            <template #default="scope">
                <el-input v-model="scope.row.model"
                          maxlength="20"
                          type="text"
                          placeholder="请输入"
                          clearable
                          show-word-limit
                />
            </template>
        </el-table-column>

        <el-table-column label="计算方式"
                         width="150"
        >
            <template #default="scope">
                <el-select v-model="scope.row.calcType"
                           @change="colChange($event, scope)"
                >
                    <el-option v-for="item in dicts.jc_zjgj_calc_type"
                               :key="item.value"
                               :label="item.label"
                               :value="Number(item.value)"
                    />
                </el-select>
            </template>
        </el-table-column>

        <el-table-column label="单位"
                         width="110"
                         prop="unit"
        />

        <el-table-column label="计算公式">
            <template #default="scope">
                <div v-if="scope.row.calcType === 2"
                     class="w-full"
                >
                    <p v-for="(item, index) in scope.row.formulaList"
                       :key="index"
                       class="mr-10 flex justify-between items-center"
                    >
                        <span class="ml-5 mr-8 c-#006dcc">
                            <span class="mr-3 c-black">公式{{ item.step }}</span>
                            {{ item.formula }}
                        </span>

                        <span class="lh-0">
                            <EditPen class="mr-8 h-16 w-16 cursor-pointer"
                                     @click="editFormula(scope, index)"
                            />

                            <Delete class="h-16 w-16 cursor-pointer"
                                    @click="colDel(scope, index)"
                            />
                        </span>
                    </p>
                </div>
            </template>
        </el-table-column>

        <el-table-column label="操作"
                         width="150"
        >
            <template #default="scope">
                <el-button v-if="scope.row.calcType === 2"
                           link
                           type="primary"
                           @click="addFormula(scope)"
                >
                    添加公式
                </el-button>

                <el-button link
                           @click="doDel(scope)"
                >
                    删除
                </el-button>
            </template>
        </el-table-column>
    </el-table>

    <el-button class="mt-20"
               type="primary"
               plain
               @click="doAdd"
    >
        + 添加计算规则
    </el-button>

    <AddDialog v-if="show"
               v-model="show"
               :is-add="isAdd"
               :data="rowData"
               :formula-idx="formulaIdx"
               @do-add="setFormula"
    />
</template>
